#!/usr/bin/env python

# browse_device.py - A pygtk2 application to demonstrate bluetooth functions
#
# Version 0.1
#
# Authors: Erin Yueh <erinyueh@gmail.com>
#
# Copyright (c) 2008 Erin Yueh
#
# browse_device.py is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# browse_device.py is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

import pygtk
pygtk.require('2.0')

import gtk, gobject
# Check for new pygtk: this is new class in PyGtk 2.4
if gtk.pygtk_version < (2,3,90):
   print "PyGtk 2.3.90 or later required for this example"
   raise SystemExit

import lightblue
import bt_adapter


class BrowseDevice:

    # close the window and quit
    def delete_event(self, widget, event, data=None):
        print 'delete_event:', widget,event
        self.w.destroy()
        return False

    def start_searching(self, b):

        dev_list = lightblue.finddevices()
        print dev_list
        i0 = None
        for dev in dev_list:
            (addr, name, class_of_service) = dev
            if addr not in self.lastseen:
                name = self.adapter.getRemoteName(addr)
                dev_type = self.adapter.getRemoteMajorClass(addr)
                pincode = self.adapter.getPinCodeLength(addr)
                if self.adapter.hasBonding(addr) == True:
                    dev_type = dev_type + " connected"
                row = (addr,name,dev_type,pincode)
                i0 = self.w.sm.get_model().append(row)
        # select the new row in each view
        if i0:
            sel = self.w.tv.get_selection()
            i1 = self.w.sm.convert_child_iter_to_iter(None, i0)
            sel.select_iter(i1)


    def search(rows, func, data):
       if not rows: return None
       for row in rows:
           if func(row, data):
               return row
           result = search(row.iterchildren(), func, data)
           if result: return result
       return None

    def search_device_inTree(self, address):
        addr_list = [ r[0] for r in self.liststore ]
        if addr_list.__contains__(address):
            return addr_list.index(address)
        else:  
            return None

    def bonding_created_cb(self, address):
        print 'bonding_created_cb', address
        index = self.search_device_inTree(address)
        if index != None:
            dev_type = self.adapter.getRemoteMajorClass(address)
            self.liststore[index][2] = dev_type + " connected"

    def bonding_removed_cb(self, address):
        print 'bonding_removed_cb', address
        index = self.search_device_inTree(address)
        if index != None:
            dev_type = self.adapter.getRemoteMajorClass(address)
            self.liststore[index][2] = dev_type + " disconnected"

    def get_BT_adapter(self):
        
        self.bt_addr = self.adapter.getAddress()
        self.bt_name = self.adapter.getName()
        self.bt_currmode = self.adapter.getMode()
        print 'bt_addr', self.bt_addr
        # list currently connected remote devices.
        self.lastseen = self.adapter.retrieve_names_fromFile()

    def col1_toggled_cb( self, treeview, path, column ):
        print 'toggle_cb'
        model = treeview.get_model()
        iter  = model.get_iter(path)
        selected_addr = model.get_value(iter,0)
        print selected_addr 
        self.connect_to_dv(selected_addr)

    def connect_to_dv(self,addr):
        print 'connecting....', addr
        if self.adapter.hasBonding(addr):
            self.adapter.removeBonding(addr)
        else:
            self.adapter.createBonding(addr)

    def __init__(self, bt):
        
        # retrieve BT adapter info
        self.adapter = bt.bluetooth_adapter

        self.get_BT_adapter()

        # create a liststore with 2 columns
        # addr,name,type,security
        self.liststore = gtk.ListStore(str,str,str,int)
        # Create new windows
        self.w = gtk.Window(gtk.WINDOW_TOPLEVEL)
        win = self.w
        win.set_title("Browse Devices")
        win.set_size_request(220, 200)
        win.connect("delete_event", self.delete_event)
        
        win.vbox = gtk.VBox()
        win.add(win.vbox)
        win.sw = gtk.ScrolledWindow()
        win.sm = gtk.TreeModelSort(self.liststore)
        # Set sort column
        win.sm.set_sort_column_id(1, gtk.SORT_ASCENDING)
        
        win.tv = gtk.TreeView(win.sm)
        win.tv.connect("row-activated", self.col1_toggled_cb)
        win.vbox.pack_start(win.sw)
        
        win.b = gtk.Button('Start Searching...')
        win.b.connect('clicked', self.start_searching)
        win.vbox.pack_start(win.b, False)
        
        win.sw.add(win.tv)
        win.tv.column = [None]*2
        win.tv.column[0] = gtk.TreeViewColumn('Name')
        win.tv.column[1] = gtk.TreeViewColumn('Device Type')
        win.tv.cell= [None]*2
        win.tv.cell[0] = gtk.CellRendererText()
        win.tv.cell[1] = gtk.CellRendererPixbuf()   
        # 'icon name', 'icon type'
        
        win.tv.column[0].set_sort_column_id(1)
        win.tv.column[0].pack_start(win.tv.cell[1], True)
        win.tv.column[0].pack_start(win.tv.cell[0], True)
        win.tv.column[0].set_attributes(win.tv.cell[1], stock_id=1)
        win.tv.column[0].set_attributes(win.tv.cell[0], text=1)
        win.tv.append_column(win.tv.column[0])
        
        win.tv.column[1].set_sort_column_id(2)
        win.tv.column[1].pack_start(win.tv.cell[0], True)
        win.tv.column[1].pack_start(win.tv.cell[1], True)
        win.tv.column[1].set_attributes(win.tv.cell[0], text=2)
        win.tv.column[1].set_attributes(win.tv.cell[1], stock_id=1)
        win.tv.append_column(win.tv.column[1])
        
        # display last seen devices
        for addr in self.lastseen:
            name = self.adapter.getRemoteName(addr)
            dev_type = self.adapter.getRemoteMajorClass(addr)
            pincode = self.adapter.getPinCodeLength(addr)
            if self.adapter.hasBonding(addr) == True:
                dev_type = dev_type + " connected"
            row = (addr,name,dev_type,pincode)
            self.w.sm.get_model().append(row)

        win.show_all()
